/**
 * @file    pcs_growatt_can.c
 * @brief   逆变器协议-古瑞瓦特-CAN通信接口V6.0
 * @author  Liuwei
 * @version 1.0.1
 * @date    2023-04-30
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-04-30 <td>1.0.1     <td>Liuwei   <td>首次创建
 * <tr><td>2023-10-12 <td>1.0.2     <td>Liuwei   <td>最高最低单体高低字节反了
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "growatt_can.h"
#include "If_can.h"
#include "var_mng.h"
#include "param_mng.h"
#include "cfg_prj.h"
#include "parallel.h"
/* macro/define --------------------------------------------------------------*/
#define GROWATT_MAX_CAP         (65000)
/* typedef -------------------------------------------------------------------*/
typedef struct 
{
    uint16_t can_id;      /* !< 报文ID */
    uint16_t send_cycle; /* !< 发送周期 */
    uint16_t send_cnt;   /* !< 计时器 */
    void(*pfunc_get_frame_msg)(can_frame_type *);
}send_frame_type;

typedef struct 
{
    uint16_t can_id;      /* !< 报文ID */
    uint8_t(*pfunc_recv_frame_msg)(can_frame_type , can_frame_type *);
}recv_frame_type;

typedef union 
{
    uint16_t status;
    struct 
    {
        uint16_t batt_state : 2;  
        uint16_t fault_flag : 1;
        uint16_t blc_state  : 1;
        uint16_t sleep_en   : 1;
        uint16_t dsg_en     : 1;
        uint16_t chg_en     : 1;
        uint16_t power_link : 1;
        uint16_t network_mode : 2;
        uint16_t force_chg  : 1;
        uint16_t rsd : 5;
    }name;
}batt_status_type;

typedef union 
{
    uint16_t half_data;
    struct pcs_growatt_can
    {
        uint16_t prechg_err : 1;
        uint16_t batt_uv : 1;
        uint16_t batt_ov : 1;
        uint16_t cell_uv : 1;
        uint16_t cell_ov: 1;
        uint16_t pack_sc : 1;
        uint16_t occ : 1;
        uint16_t ocd : 1;

        uint16_t ver_diff : 1;
        uint16_t parallel_err : 1;
        uint16_t volt_diff_ov;
        uint16_t sys_err;
        uint16_t utc : 1;
        uint16_t utd : 1;
        uint16_t otc : 1;
        uint16_t otd : 1;
    }name;
}protect_msg_type;

typedef union 
{
    uint16_t half_data;
    struct 
    {
        uint16_t rsd0 : 1;
        uint16_t batt_uv : 1;
        uint16_t batt_ov : 1;
		uint16_t cell_uv : 1;
        uint16_t cell_ov : 1;
		uint16_t rsd1 : 1;
	    uint16_t occ : 1;
        uint16_t ocd : 1;

        uint16_t comm_err : 1;
        uint16_t power_off : 1;
        uint16_t volt_diff_ov;
        uint16_t rsd2;
        uint16_t utc : 1;
        uint16_t utd : 1;
        uint16_t otc : 1;
        uint16_t otd : 1;
    }name;
}alarm_msg_type;

typedef union 
{
    uint16_t half_data;
    struct
    {
        uint16_t hard_err : 1;
        uint16_t full_chg : 1;
        uint16_t most_oh  : 1;
        uint16_t envt_oh  : 1;
        uint16_t prechg_err : 1;
        uint16_t comm_err : 1;
        uint16_t bus_err : 1;
        uint16_t rsd0 : 1;

        uint16_t cell_ov : 1;
        uint16_t cell_uv : 1;
        uint16_t temp_oh : 1;
        uint16_t temp_ol : 1;
        uint16_t batt_ov : 1;
        uint16_t batt_uv : 1;
        uint16_t vdiff_ov : 1;
        uint16_t tdiff_oh : 1;
    }name;
}pow_down_reason_type;

typedef union
{
    uint8_t byte_data;
    struct 
    {
        uint8_t batt_type : 2;
        uint8_t rsd : 2;
        uint8_t force_chg2 : 1;
        uint8_t force_chg1 : 1;
        uint8_t dsg_en : 1;
        uint8_t chg_en : 1;
    }name;
}ask_msg_type;

#define ALARM_UN_SUP   (0)   /* 不支持故障 */
#define ALARM_HAPPEN   (1)   /* 发生 */
#define ALARM_NORMAL   (2)   /* 正常 */
/* local functions -----------------------------------------------------------*/
static void can_get_0x311_msg(can_frame_type *can_msg);
static void can_get_0x312_msg(can_frame_type *can_msg);
static void can_get_0x313_msg(can_frame_type *can_msg);
static void can_get_0x314_msg(can_frame_type *can_msg);
static void can_get_0x319_msg(can_frame_type *can_msg);
static void can_get_0x320_msg(can_frame_type *can_msg);
//static void can_get_0x321_msg(can_frame_type *can_msg);
static void can_get_0x322_msg(can_frame_type *can_msg);
static void can_get_0x323_msg(can_frame_type *can_msg);
static uint8_t can_get_0x324_msg(can_frame_type *can_msg);
static uint8_t can_get_0x325_msg(can_frame_type *can_msg);

static uint8_t can_recv_0x301_msg(can_frame_type can_recv,can_frame_type *can_send);
static uint8_t can_recv_0x211_msg(can_frame_type can_recv ,can_frame_type *can_send);
static uint8_t can_recv_0x212_msg(can_frame_type can_recv ,can_frame_type *can_send);
/* static variables ----------------------------------------------------------*/
static send_frame_type send_frame_list[] = 
{
    {0x311 , 500 , 0 ,can_get_0x311_msg },
    {0x312 , 500 , 0 ,can_get_0x312_msg },
    {0x313 , 500 , 0 ,can_get_0x313_msg },
    {0x314 , 500 , 0 ,can_get_0x314_msg },
    {0x319 , 500 , 0 ,can_get_0x319_msg },
    {0x320 , 500 , 0 ,can_get_0x320_msg },
 //   {0x321 , 500 , 0 ,can_get_0x321_msg },
	{0x322 , 500 , 0 ,can_get_0x322_msg },
	{0x323 , 500 , 0 ,can_get_0x323_msg },
};

static recv_frame_type recv_frame_list[] = 
{
    {0x301 ,  can_recv_0x301_msg},
    {0x211 ,  can_recv_0x211_msg},
    {0x212 ,  can_recv_0x212_msg},
};

#define CAN_LIST_NUM     (sizeof(send_frame_list)/sizeof(send_frame_type))
#define RECV_LIST_NUM    (sizeof(recv_frame_list)/sizeof(recv_frame_type))
/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
/**
 * @brief  获取需要发送的数据信息
 * @param  cycle
 * @param  can_buf
 * @return uint8_t 
 */
uint8_t growatt_can_deal_msg(uint32_t cycle , can_frame_type *can_buf , uint8_t recv_num ,const can_frame_type *recv_msg)
{
    uint8_t i = 0;
	uint8_t j = 0;
    uint8_t msg_num = 0;

    for( i = 0; i < CAN_LIST_NUM; ++ i)
    {
        send_frame_list[i].send_cnt += cycle;
        if(send_frame_list[i].send_cnt >= send_frame_list[i].send_cycle)
        {
            send_frame_list[i].send_cnt = 0;
            send_frame_list[i].pfunc_get_frame_msg(&can_buf[msg_num ++]); 
        }
    }

    for( i = 0;i < recv_num; ++ i)
    {
        for( j = 0;j < RECV_LIST_NUM; ++ j)
        if(recv_frame_list[j].can_id == recv_msg[i].id)
        {
            msg_num += recv_frame_list[j].pfunc_recv_frame_msg(recv_msg[i] , &can_buf[msg_num]);
        }
    }

    return msg_num;
}

/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
static void can_get_0x311_msg(can_frame_type *can_msg)
{
    batt_status_type run_state = {0};
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x311;
	
	if(master_data_reg.total_bus_curr > 0)
		run_state.name.batt_state = 0x02;
	else if(master_data_reg.total_bus_curr < 0)
		run_state.name.batt_state = 0x03;
	else
		run_state.name.batt_state = 0x01;
	run_state.name.blc_state = 0;
	run_state.name.sleep_en = 0;
	run_state.name.fault_flag = master_data_reg.total_prp_msg.bit.sc | master_data_reg.total_prp_msg.bit.fcmos |
	                         master_data_reg.total_prp_msg.bit.fdmos |master_data_reg.total_prp_msg.bit.afe_err |
	                         master_data_reg.total_prp_msg.bit.col | master_data_reg.total_prp_msg.bit.tol;
	run_state.name.dsg_en = parallel_get_pcs_ctrl(PARALLEL_PCS_DSG_EN);
	run_state.name.chg_en = parallel_get_pcs_ctrl(PARALLEL_PCS_CHG_EN);
	if (master_data_reg.parallel_num <= 1)
		run_state.name.network_mode = 0x00;
	else
		run_state.name.network_mode = 0x02;
	run_state.name.force_chg = parallel_get_pcs_ctrl(PARALLEL_PCS_FROCE_CHG1);
	
    can_msg->data.half_buf[0] = LIT_TO_BIG(var_get_data(VAR_ID_TP_SOP_CV));
    can_msg->data.half_buf[1] = LIT_TO_BIG(var_get_data(VAR_ID_TP_SOP_CC));
    can_msg->data.half_buf[2] = LIT_TO_BIG(var_get_data(VAR_ID_TP_SOP_DC)); 
    can_msg->data.half_buf[3] = LIT_TO_BIG(run_state.status);  //最新逆变器识别
}

extern master_data_type master_data_reg;
static void can_get_0x312_msg(can_frame_type *can_msg)
{
    alarm_msg_type alarm_msg = {0};
    protect_msg_type prp_msg = {0};
	
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x312;
	
	prp_msg.name.occ = master_data_reg.total_prp_msg.bit.occ | master_data_reg.total_prp_msg.bit.occ2;
	prp_msg.name.ocd = master_data_reg.total_prp_msg.bit.ocd | master_data_reg.total_prp_msg.bit.ocd2;
	
	prp_msg.name.otc = master_data_reg.total_prp_msg.bit.otc;
	prp_msg.name.otd = master_data_reg.total_prp_msg.bit.otd;
	prp_msg.name.utc = master_data_reg.total_prp_msg.bit.utc;
	prp_msg.name.utd = master_data_reg.total_prp_msg.bit.utd;
	prp_msg.name.pack_sc = master_data_reg.total_prp_msg.bit.sc;
	
    can_msg->data.half_buf[0] = LIT_TO_BIG(prp_msg.half_data);
    can_msg->data.half_buf[1] = LIT_TO_BIG(alarm_msg.half_data);
    can_msg->data.byte_buf[4] = master_data_reg.parallel_num;
    can_msg->data.byte_buf[5] = 0;
	can_msg->data.byte_buf[6] = 0;
	can_msg->data.byte_buf[7] = param_get_data(PAR_ID_CB_CELL_NUM) * master_data_reg.parallel_num;
}

static void can_get_0x313_msg(can_frame_type *can_msg)
{
    int16_t curr = 0;
    int32_t temp = 0;
	uint8_t soh = 0;
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x313;

    can_msg->data.half_buf[0] = LIT_TO_BIG(var_get_data(VAR_ID_TP_VOLT));
    temp = (var_get_data(VAR_ID_TP_CURR_H) << 16) + var_get_data(VAR_ID_TP_CURR_L);
    curr = temp * 0.1;
    can_msg->data.half_buf[1] = LIT_TO_BIG(curr);
    can_msg->data.half_buf[2] = LIT_TO_BIG(var_get_data(VAR_ID_TP_AVG_TEMP) - 2731);
    can_msg->data.byte_buf[6] = var_get_data(VAR_ID_TP_SOC);
	soh = var_get_data(VAR_ID_TP_SOH);
	if(soh > 100)
		soh = 100;
    can_msg->data.byte_buf[7] = soh;
}

static void can_get_0x314_msg(can_frame_type *can_msg)
{
	uint32_t v32_val = 0;
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x314;
	
	v32_val = master_data_reg.total_real_cap;
	if(v32_val > GROWATT_MAX_CAP)
		v32_val = GROWATT_MAX_CAP;
    can_msg->data.half_buf[0] = LIT_TO_BIG(v32_val);
	
	v32_val = master_data_reg.total_full_cap;
	if(v32_val > GROWATT_MAX_CAP)
		v32_val = GROWATT_MAX_CAP;
    can_msg->data.half_buf[1] = LIT_TO_BIG(v32_val);
	
    can_msg->data.half_buf[2] = LIT_TO_BIG(var_get_data(VAR_ID_TP_MAXC_VOLT) - var_get_data(VAR_ID_TP_MINC_VOLT));
    can_msg->data.half_buf[3] = LIT_TO_BIG(var_get_data(VAR_ID_TP_CYCLE));
}

static void can_get_0x319_msg(can_frame_type *can_msg)
{
    ask_msg_type ask_msg = {0};
    uint16_t temp = 0;
    
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x319;
   
	ask_msg.name.chg_en = parallel_get_pcs_ctrl(PARALLEL_PCS_CHG_EN);
	ask_msg.name.dsg_en = parallel_get_pcs_ctrl(PARALLEL_PCS_DSG_EN);
	ask_msg.name.force_chg1 = parallel_get_pcs_ctrl(PARALLEL_PCS_FROCE_CHG1);
	ask_msg.name.force_chg2 = parallel_get_pcs_ctrl(PARALLEL_PCS_FROCE_CHG2);
    can_msg->data.byte_buf[0] = ask_msg.byte_data;

    temp = LIT_TO_BIG(var_get_data(VAR_ID_TP_MAXC_VOLT));
    can_msg->data.byte_buf[1] = temp & 0xff;
    can_msg->data.byte_buf[2] = temp >> 8;

    temp = LIT_TO_BIG(var_get_data(VAR_ID_TP_MINC_VOLT));
    can_msg->data.byte_buf[3] = temp & 0xff;
    can_msg->data.byte_buf[4] = temp >> 8;
	
    can_msg->data.byte_buf[5] = var_get_data(VAR_ID_TP_MAXC_SN);
    can_msg->data.byte_buf[6] = var_get_data(VAR_ID_TP_MINC_SN);

    can_msg->data.byte_buf[7] = 0;
}

static void can_get_0x320_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x320;

    can_msg->data.byte_buf[0] = 'G';
	can_msg->data.byte_buf[1] = 'T';
    can_msg->data.byte_buf[2] = var_get_data(VAR_ID_HARD_VER);
    can_msg->data.byte_buf[3] = SOFT_VER_RELEASE;
    can_msg->data.byte_buf[4] = SOFT_VER_MAIN;
    can_msg->data.byte_buf[5] = SOFT_VER_RELEASE;
    can_msg->data.byte_buf[6] = SOFT_VER_MAIN;
    can_msg->data.byte_buf[7] = 0;
}

//static void can_get_0x321_msg(can_frame_type *can_msg)
//{
//    can_msg->frame_type = CAN_FRAME_DATA;
//    can_msg->id_type = CAN_ID_STD;
//    can_msg->dlc = 8;
//    can_msg->id = 0x321;
//    
//    can_msg->data.half_buf[0] = 0;
//    can_msg->data.half_buf[1] = 0;
//    can_msg->data.half_buf[2] = 0;
//    can_msg->data.half_buf[3] = 0;
//}

static void can_get_0x322_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x322;
   
    can_msg->data.half_buf[0] = LIT_TO_BIG(var_get_data(VAR_ID_TP_MAXT_VAL) - 2731);
    can_msg->data.half_buf[1] = LIT_TO_BIG(var_get_data(VAR_ID_TP_MINT_VAL) - 2731);
    can_msg->data.byte_buf[4] = var_get_data(VAR_ID_TP_MAXT_SN);
    can_msg->data.byte_buf[5] = var_get_data(VAR_ID_TP_MINT_SN);
    can_msg->data.byte_buf[6] = var_get_data(VAR_ID_TP_SOC);
    can_msg->data.byte_buf[7] = var_get_data(VAR_ID_TP_SOC);
}

static void can_get_0x323_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x323;
   
    can_msg->data.byte_buf[0] = param_get_data(PAR_ID_CB_CELL_NUM) * master_data_reg.parallel_num;
    can_msg->data.byte_buf[1] = (param_get_data(PAR_ID_COV_ALM_VAL) >>8 )& 0xFF;
	can_msg->data.byte_buf[2] = param_get_data(PAR_ID_COV_ALM_VAL) & 0xFF;
	can_msg->data.byte_buf[3] = 0;
    can_msg->data.byte_buf[4] = 0;
    can_msg->data.byte_buf[5] = 0;
    can_msg->data.byte_buf[6] = 0;
    can_msg->data.byte_buf[7] = 0;
}

static uint8_t can_get_0x324_msg(can_frame_type *can_msg)
{
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x324;
    
    can_msg->data.byte_buf[0] = 0;    
	can_msg->data.byte_buf[1] = 0;
    can_msg->data.byte_buf[2] = 0;
    can_msg->data.byte_buf[3] = 0;

    can_msg->data.word_buf[1] = 0;
	
	return 1;
}

static uint8_t can_get_0x325_msg(can_frame_type *can_msg)
{
	/* BMS名称 */
	can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x372;
    
    can_msg->data.half_buf[0] = 0xFFFF; /*0:正常 1:强制充电 2:强制待机 */
    can_msg->data.half_buf[1] = 0xFFFF;
    can_msg->data.half_buf[2] = 0xFFFF;
    can_msg->data.half_buf[3] = 0xFFFF;
	
	return 1;
}

static uint8_t can_recv_0x301_msg(can_frame_type can_recv,can_frame_type *can_send)
{
	return 1;
}

static uint8_t can_recv_0x211_msg(can_frame_type can_recv ,can_frame_type *can_send)
{
	// uint8_t year = 0;
    // uint8_t mon = 0;
    // uint8_t date = 0;
    // uint8_t hour = 0;
    // uint8_t min = 0;
    // uint8_t sec = 0;

    // year = can_recv.data.byte_buf[1];
    // mon = can_recv.data.byte_buf[2];
    // date = can_recv.data.byte_buf[3];
    // hour = can_recv.data.byte_buf[4];
    // min = can_recv.data.byte_buf[5];
    // sec = can_recv.data.byte_buf[6];
	
	return 1;
}

static uint8_t can_recv_0x212_msg(can_frame_type can_recv ,can_frame_type *can_send)
{
	// can_get_0x321_msg(can_send);
	can_get_0x324_msg(can_send++);
	can_get_0x325_msg(can_send++);
	return 2;
}

/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/


